/*
 * Author: vdaras
 */

#ifndef STATE_H
#define	STATE_H

#include "NonCopyable.h"

#include "gui/ActionListener.h"
#include "gui/Container.h"
#include "sdl/GraphicsCore.h"
#include "physics/PhysicsManager.h"
#include "EntityManager.h"
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "audio/AudioManager.h"

/**
 * Interface class used to implement the State design pattern. These States are
 * used to change the guts of the Engine's functionality by enforcing a protocol
 * to implementers. A State has:
 *
 * - a rendering manager
 * - a level map
 * - a gui container
 * - a pool of entities supported by a physics manager.
 *
 * These can be used to create either menus or gameplay with huds.
 *
 * See the State's methods in order to understand how someone can alter the
 * Engine's behavior.
 */

using physicsSystem::PhysicsManager;
using EntitySystem::EntityManager;
using al::AudioManager;

class EngineCore;
class LevelMap;
class RenderingManager;
class TileProperties;

class State : public gui::ActionListener, public NonCopyable
{
    friend class StateStack;

private:
    gui::Container *m_guiContents;

    TileProperties *m_tileProperties;

    LevelMap *m_levelMap;

    EntityManager *m_entityManager;
    
    bool ignoreNotifications;

public:

    al::AudioManager *m_audioManager;

    PhysicsManager *m_physicsManager;

    RenderingManager *m_renderingManager;

public:

    State(EngineCore *engine);


    virtual ~State();


    /**
     * Renders this State.
     *
     * @param gCore - handle to the engine's graphics core.
     */

    virtual void Render(sdl::GraphicsCore *gCore);



    virtual void Create() = 0;


    /**
     * Updates the State by updating the Entity, Physics and Audio managers.
     *
     * @param deltaTime - time passed since last call.
     */

    virtual void Update(unsigned deltaTime) = 0;

    /**
     * Receives a message from an entity.
     *
     */

    virtual void OnEntityMessage(EntitySystem::Entity* sender,const std::string& msg) = 0;


    /**
     * Pushes keyboard events to the Entities. Override to extend functionality.
     *
     * @param event: a keyboard event occurred.
     */

    virtual void OnKeyboardEvent(KeyboardEvent& event) = 0;


    /**
     * Override to extend functionality. 
     * TODO Push Mouse Events to the Entities. 
     * 
     * @param event: a mouse event occurred. 
     */

    virtual void OnMouseEvent(MouseEvent& event) = 0;


    /**
     * Pauses this State. Override to provide functionality.
     */

    virtual void Pause() = 0;


    /**
     * Resumes this State. Override to provide functionality.
     */

    virtual void Resume() = 0;


    /**
     * Gets called when this State is removed from the State Stack. Override
     * to provide functionality.
     */

    virtual void Cleanup() = 0;


    virtual void ActionPerformed(gui::Component *sender) = 0;


    /**
     * @return A pointer to the State's rendering manager.
     */

    RenderingManager *GetRenderingManager();


    /**
     * @return A pointer to the State's entity manager.
     */

    EntityManager *GetEntityManager();


    /**
     * @return A pointer to the State's physics manager.
     */

    PhysicsManager *GetPhysicsManager();


    /**
     * 
     * @return A pointer to the State's Audio Manager. 
     */

    AudioManager *GetAudioManager();


    /**
     * Loads a tile map.
     *
     * @param mapName - name of the map to load.
     * @param layerName - layer to register the map on.
     * @return a boolean value indicating if loading was successful or not.
     */

    bool LoadMap(const std::string& mapName, const std::string& layerName);
    
    void UnLoadMap();

    /**
     * Returns a pointer to the gui contents of this State.
     *
     * @return a gui::Container that belongs to this State.
     */

    gui::Container* GuiContents();
};

#endif	/* STATE_H */

